/*
 * Copyright (c) 2022 PATEO CONNECT+ (Nanjing) Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "voice_assistant_client_callback_proxy.h"
#include "common_utils.h"
#include "iremote_object.h"
#include "iremote_proxy.h"
#include "voice_assistant_log.h"

using namespace OHOS::CarVoiceAssistant::CommonUtils;

namespace OHOS {
namespace CarVoiceAssistant {

#define WRITE_PARCEL_WITH_RET(parcel, type, data, retval)                        \
    do {                                                                         \
        if (!(parcel).Write##type(data)) {                                       \
            VOICE_ASSISTANT_LOGI("%{public}s write " #data " failed", __func__); \
            return (retval);                                                     \
        }                                                                        \
    } while (0)

#define READ_PARCEL_WITH_RET(parcel, type, out, retval)                        \
    do {                                                                       \
        if (!(parcel).Read##type(out)) {                                       \
            VOICE_ASSISTANT_LOGI("%{public}s read " #out " failed", __func__); \
            return (retval);                                                   \
        }                                                                      \
    } while (0)

    VoiceAssistantClientCallbackProxy::VoiceAssistantClientCallbackProxy(const sptr<IRemoteObject>& impl)
        : IRemoteProxy<IVoiceAssistantClientCallback>(impl)
    {
    }

    size_t VoiceAssistantClientCallbackProxy::NotifyWakeUp()
    {
        VOICE_ASSISTANT_LOGI("NotifyWakeUp");
        MessageParcel data;
        MessageParcel reply;
        CommonUtils::VoiceAssistantErrorCode code = DoDispatch(VOICE_ASSITANT_CALLBACK_ON_WAKEUP, data, reply);
        if (code != VOICE_ASSISTANT_OK) {
            VOICE_ASSISTANT_LOGI("NotifyWakeUp failed");
            return code;
        }
        return VOICE_ASSISTANT_OK;
    }

    size_t VoiceAssistantClientCallbackProxy::NotifyRecognizeStateChanged(bool isRecognizing)
    {
        VOICE_ASSISTANT_LOGI("NotifyRecognizeStateChanged:%{public}s", isRecognizing ? "true" : "false");
        MessageParcel data;
        MessageParcel reply;

        WRITE_PARCEL_WITH_RET(data, Bool, isRecognizing, VOICE_ASSISTANT_ERR);

        CommonUtils::VoiceAssistantErrorCode code = DoDispatch(VOICE_ASSITANT_CALLBACK_RECOGNIZE_STATE_CHANGED, data, reply);
        if (code != VOICE_ASSISTANT_OK) {
            VOICE_ASSISTANT_LOGI("NotifyRecognizeStateChanged failed");
            return code;
        }
        return VOICE_ASSISTANT_OK;
    }

    size_t VoiceAssistantClientCallbackProxy::NotifyAsrResult(std::string result)
    {
        VOICE_ASSISTANT_LOGI("NotifyAsrResult:%{public}s", result.c_str());
        MessageParcel data;
        MessageParcel reply;

        WRITE_PARCEL_WITH_RET(data, String, result, VOICE_ASSISTANT_ERR);

        CommonUtils::VoiceAssistantErrorCode code = DoDispatch(VOICE_ASSITANT_CALLBACK_ASR_RESULT, data, reply);
        if (code != VOICE_ASSISTANT_OK) {
            VOICE_ASSISTANT_LOGI("NotifyAsrResult failed");
            return code;
        }
        return VOICE_ASSISTANT_OK;
    }

    size_t VoiceAssistantClientCallbackProxy::NotifyTTSPlayStateChanged(bool isPlaying)
    {
        VOICE_ASSISTANT_LOGI("NotifyTTSPlayStateChanged:%{public}s", isPlaying ? "true" : "false");
        MessageParcel data;
        MessageParcel reply;

        WRITE_PARCEL_WITH_RET(data, Bool, isPlaying, VOICE_ASSISTANT_ERR);

        CommonUtils::VoiceAssistantErrorCode code = DoDispatch(VOICE_ASSISTANT_CALLBACK_TTS_STATE_CHANGED, data, reply);
        if (code != VOICE_ASSISTANT_OK) {
            VOICE_ASSISTANT_LOGI("NotifyTTSPlayStateChanged failed");
            return code;
        }
        return VOICE_ASSISTANT_OK;
    }

    CommonUtils::VoiceAssistantErrorCode VoiceAssistantClientCallbackProxy::DoDispatch(uint32_t cmd, MessageParcel& data, MessageParcel& reply)
    {
        VOICE_ASSISTANT_LOGI("%{public}s:%{public}d cmd:%{public}d", __func__, __LINE__, cmd);

        MessageOption option;
        auto ret = Remote()->SendRequest(cmd, data, reply, option);
        VOICE_ASSISTANT_LOGI("%{public}s:%{public}d SendRequest end cmd:%{public}d ", __func__, __LINE__, cmd);
        if (ret != ERR_NONE) {
            VOICE_ASSISTANT_LOGI("failed to send request, cmd: %{public}d, ret: %{public}d", cmd, ret);
            return VOICE_ASSISTANT_ERR;
        }
        VOICE_ASSISTANT_LOGI(" success to dispatch cmd: %{public}d", cmd);
        return VOICE_ASSISTANT_OK;
    }
}
}